/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package optimization;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.lang.*;
import java.util.LinkedList;

/**
 *
 * @author yulian
 */
public class Parser {

	public LinkedList<Field> getSelect_List() {
		return Select_List;
	}

	public LinkedList<Field> getTable_List() {
		return Table_List;
	}

	public LinkedList<Condition> getJoin_List() {
		return Join_List;
	}

	public LinkedList<Condition> getBooleanExp_List() {
		return BooleanExp_List;
	}

	public void parse(String inputSQL) throws SQLParsingException {
		inputSQL = inputSQL.replaceFirst(" where ", " WHERE ");
		inputSQL = inputSQL.replaceFirst("select ", " SELECT ");
		inputSQL = inputSQL.replaceFirst(" from ", " FROM ");
		inputSQL = inputSQL.replaceAll(" and ", " AND ");
		if (inputSQL.indexOf("SELECT") == -1) {
			throw new SQLParsingException("SELECT missing");
		}
		if (inputSQL.indexOf("FROM") == -1) {
			throw new SQLParsingException("FROM missing");
		}
		String[] before_from_after_select = null;
		before_from_after_select = inputSQL.split("SELECT");
		before_from_after_select = before_from_after_select[1].split("FROM");
		before_from_after_select = before_from_after_select[0]
				.split("\\s+|\\,|\\'|\\(|\\)|\\\"");
		LinkedList<String> before_from_after_select_list = new LinkedList<String>();
		for (int i = 0; i < before_from_after_select.length; i++) {
			if (before_from_after_select[i].length() != 0) {
				if (before_from_after_select[i].indexOf(".") != -1) {
					String temp1[] = null;
					temp1 = before_from_after_select[i].split("\\.");
					before_from_after_select[i] = temp1[1];
				}
				if (before_from_after_select[i].compareToIgnoreCase("item") == 0
						|| before_from_after_select[i]
								.compareToIgnoreCase("unitquantity") == 0
						|| before_from_after_select[i]
								.compareToIgnoreCase("price") == 0
						|| before_from_after_select[i]
								.compareToIgnoreCase("ingredient") == 0
						|| before_from_after_select[i]
								.compareToIgnoreCase("servingquantity") == 0
						|| before_from_after_select[i]
								.compareToIgnoreCase("mealtime") == 0
						|| before_from_after_select[i]
								.compareToIgnoreCase("day") == 0
						|| before_from_after_select[i]
								.compareToIgnoreCase("budgetleft") == 0
						|| before_from_after_select[i]
								.compareToIgnoreCase("menu") == 0) {
				} else {
					throw new SQLParsingException("ITEM "
							+ before_from_after_select[i] + " incorrect");
				}
				before_from_after_select_list.add(before_from_after_select[i]);
			}
		}
		for (int i = 0; i < before_from_after_select_list.size(); i++) {
			if (before_from_after_select_list.get(i)
					.compareToIgnoreCase("item") == 0) {
				this.Select_List.add(new Field(tab_name_att_name.SUPPLIES,
						tab_name_att_name.ITEM));
			} else if (before_from_after_select_list.get(i)
					.compareToIgnoreCase("unitquantity") == 0) {
				this.Select_List.add(new Field(tab_name_att_name.SUPPLIES,
						tab_name_att_name.UNITQUANTITY));
			} else if (before_from_after_select_list.get(i)
					.compareToIgnoreCase("price") == 0) {
				this.Select_List.add(new Field(tab_name_att_name.SUPPLIES,
						tab_name_att_name.PRICE));
			} else if (before_from_after_select_list.get(i)
					.compareToIgnoreCase("ingredient") == 0) {
				this.Select_List.add(new Field(tab_name_att_name.RECIPE,
						tab_name_att_name.INGREDIENT));
			} else if (before_from_after_select_list.get(i)
					.compareToIgnoreCase("servingquantity") == 0) {
				this.Select_List.add(new Field(tab_name_att_name.RECIPE,
						tab_name_att_name.SERVINGQUANTITY));
			} else if (before_from_after_select_list.get(i)
					.compareToIgnoreCase("mealtime") == 0) {
				this.Select_List.add(new Field(tab_name_att_name.BUDGET,
						tab_name_att_name.MEALTIME));
			} else if (before_from_after_select_list.get(i)
					.compareToIgnoreCase("day") == 0) {
				this.Select_List.add(new Field(tab_name_att_name.BUDGET,
						tab_name_att_name.DAY));
			} else if (before_from_after_select_list.get(i)
					.compareToIgnoreCase("budgetleft") == 0) {
				this.Select_List.add(new Field(tab_name_att_name.BUDGET,
						tab_name_att_name.BUDGETLEFT));
			} else if (before_from_after_select_list.get(i)
					.compareToIgnoreCase("menu") == 0) {
				this.Select_List.add(new Field(tab_name_att_name.RECIPE,
						tab_name_att_name.MENU));
			}
		}
		String[] before_where_after_from = null;
		before_where_after_from = inputSQL.split("FROM");
		if (inputSQL.indexOf("WHERE") != -1) {
			before_where_after_from = before_where_after_from[1].split("WHERE");
			before_where_after_from = before_where_after_from[0]
					.split("\\s+|\\,|\\'|\\(|\\)|\\\"");
		} else {
			before_where_after_from = before_where_after_from[1]
					.split("\\s+|\\,|\\'|\\(|\\)|\\\"");
		}
		LinkedList<String> before_where_after_from_list = new LinkedList<String>();
		for (int i = 0; i < before_where_after_from.length; i++) {
			if (before_where_after_from[i].length() != 0) {
				if (before_where_after_from[i].compareToIgnoreCase("supplies") == 0
						|| before_where_after_from[i]
								.compareToIgnoreCase("recipe") == 0
						|| before_where_after_from[i]
								.compareToIgnoreCase("budget") == 0) {
				} else {
					throw new SQLParsingException("TABLE "
							+ before_where_after_from[i] + " incorrect");
				}
				before_where_after_from_list.add(before_where_after_from[i]);
			}
		}
		boolean[] table_accessed = new boolean[3];
		for (int i = 0; i < before_where_after_from_list.size(); i++) {
			if (before_where_after_from_list.get(i).compareToIgnoreCase(
					"supplies") == 0) {
				table_accessed[tab_name_att_name.SUPPLIES.ordinal()] = true;
			} else if (before_where_after_from_list.get(i).compareToIgnoreCase(
					"recipe") == 0) {
				table_accessed[tab_name_att_name.RECIPE.ordinal()] = true;
			} else if (before_where_after_from_list.get(i).compareToIgnoreCase(
					"budget") == 0) {
				table_accessed[tab_name_att_name.BUDGET.ordinal()] = true;
			}
		}
		if (table_accessed[0] == true) {
			Table_List.add(new Field(tab_name_att_name.SUPPLIES));
		}
		if (table_accessed[1] == true) {
			Table_List.add(new Field(tab_name_att_name.RECIPE));
		}
		if (table_accessed[2] == true) {
			Table_List.add(new Field(tab_name_att_name.BUDGET));
		}
		if (inputSQL.indexOf("WHERE") != -1) {
			LinkedList<String> after_where_list = new LinkedList<String>();
			String[] after_where = null;
			after_where = inputSQL.split("WHERE");
			after_where = after_where[1].split("AND");
			for (int i = 0; i < after_where.length; i++) {
				if (after_where[i].length() != 0) {
					after_where_list.add(after_where[i]);
					//System.out.println(after_where[i]);
				}
			}
			for (int i = 0; i < after_where_list.size(); i++) {
				String temp[] = after_where_list.get(i).split(
						"\\s+|\\>|\\<|\\!|\\=");

				LinkedList<String> temp_list = new LinkedList<String>();
				for (int j = 0; j < temp.length; j++) {
					if (temp[j].length() != 0) {
						temp_list.add(temp[j]);
					}
				}
				Condition con = new Condition();

				if (temp_list.get(0).length() != 0) {

					//.out.println("temp 0 " + temp_list.get(0));
					if (after_where_list.get(i).indexOf(">") != -1) {
						if (after_where_list.get(i).indexOf("=") != -1) {
							con.operator = operator_type.LARGER_OR_EQUAL;
						} else {
							con.operator = operator_type.LARGER;
						}
					} else if (after_where_list.get(i).indexOf("<") != -1) {
						if (after_where_list.get(i).indexOf("=") != -1) {
							con.operator = operator_type.SMALLER_OR_EQUAL;
						} else {
							con.operator = operator_type.SMALLER;
						}
					} else if (after_where_list.get(i).indexOf("!") != -1) {
						if (after_where_list.get(i).indexOf("=") != -1) {
							con.operator = operator_type.NOT_EQUAL;
						} else {
							throw new SQLParsingException("EQUAL missing");
						}
					} else if (after_where_list.get(i).indexOf("=") != -1) {
						con.operator = operator_type.EQUAL;
					}
					if (temp_list.get(0).compareToIgnoreCase("item") == 0) {
						con.lhs.item_name = tab_name_att_name.ITEM;
						con.lhs.table_name = tab_name_att_name.SUPPLIES;
					} else if (temp_list.get(0).compareToIgnoreCase(
							"unitquantity") == 0) {
						con.lhs.item_name = tab_name_att_name.UNITQUANTITY;
						con.lhs.table_name = tab_name_att_name.SUPPLIES;
					} else if (temp_list.get(0).compareToIgnoreCase("price") == 0) {
						con.lhs.item_name = tab_name_att_name.PRICE;
						con.lhs.table_name = tab_name_att_name.SUPPLIES;
					} else if (temp_list.get(0).compareToIgnoreCase("menu") == 0) {
						con.lhs.item_name = tab_name_att_name.MENU;
						con.lhs.table_name = tab_name_att_name.RECIPE;
					} else if (temp_list.get(0).compareToIgnoreCase(
							"ingredient") == 0) {
						con.lhs.item_name = tab_name_att_name.INGREDIENT;
						con.lhs.table_name = tab_name_att_name.RECIPE;
					} else if (temp_list.get(0).compareToIgnoreCase(
							"servingquantity") == 0) {
						con.lhs.item_name = tab_name_att_name.SERVINGQUANTITY;
						con.lhs.table_name = tab_name_att_name.RECIPE;
					} else if (temp_list.get(0).compareToIgnoreCase("mealtime") == 0) {
						con.lhs.item_name = tab_name_att_name.MEALTIME;
						con.lhs.table_name = tab_name_att_name.BUDGET;
					} else if (temp_list.get(0).compareToIgnoreCase("day") == 0) {
						con.lhs.item_name = tab_name_att_name.DAY;
						con.lhs.table_name = tab_name_att_name.BUDGET;
					} else if (temp_list.get(0).compareToIgnoreCase(
							"budgetleft") == 0) {
						con.lhs.item_name = tab_name_att_name.BUDGETLEFT;
						con.lhs.table_name = tab_name_att_name.BUDGET;
					} else {
						con.lhs.item_name = tab_name_att_name.NULL;
						con.lhs.table_name = tab_name_att_name.NULL;
						con.lhs_s = temp_list.get(0);
					}

				}
				if (temp_list.get(1).length() != 0) {
					if (temp_list.get(1).compareToIgnoreCase("item") == 0) {
						con.rhs.item_name = tab_name_att_name.ITEM;
						con.rhs.table_name = tab_name_att_name.SUPPLIES;
					} else if (temp_list.get(1).compareToIgnoreCase(
							"unitquantity") == 0) {
						con.rhs.item_name = tab_name_att_name.UNITQUANTITY;
						con.rhs.table_name = tab_name_att_name.SUPPLIES;
					} else if (temp_list.get(1).compareToIgnoreCase("price") == 0) {
						con.rhs.item_name = tab_name_att_name.PRICE;
						con.rhs.table_name = tab_name_att_name.SUPPLIES;
					} else if (temp_list.get(1).compareToIgnoreCase("menu") == 0) {
						con.rhs.item_name = tab_name_att_name.MENU;
						con.rhs.table_name = tab_name_att_name.RECIPE;
					} else if (temp_list.get(1).compareToIgnoreCase(
							"ingredient") == 0) {
						con.rhs.item_name = tab_name_att_name.INGREDIENT;
						con.rhs.table_name = tab_name_att_name.RECIPE;
					} else if (temp_list.get(1).compareToIgnoreCase(
							"servingquantity") == 0) {
						con.rhs.item_name = tab_name_att_name.SERVINGQUANTITY;
						con.rhs.table_name = tab_name_att_name.RECIPE;
					} else if (temp_list.get(1).compareToIgnoreCase("mealtime") == 0) {
						con.rhs.item_name = tab_name_att_name.MEALTIME;
						con.rhs.table_name = tab_name_att_name.BUDGET;
					} else if (temp_list.get(1).compareToIgnoreCase("day") == 0) {
						con.rhs.item_name = tab_name_att_name.DAY;
						con.rhs.table_name = tab_name_att_name.BUDGET;
					} else if (temp_list.get(1).compareToIgnoreCase(
							"budgetleft") == 0) {
						con.rhs.item_name = tab_name_att_name.BUDGETLEFT;
						con.rhs.table_name = tab_name_att_name.BUDGET;
					} else {
						con.rhs.item_name = tab_name_att_name.NULL;
						con.rhs.table_name = tab_name_att_name.NULL;
						con.rhs_s = temp_list.get(1);
					}

				}
				if (con.lhs.table_name != tab_name_att_name.NULL
						&& con.rhs.table_name != tab_name_att_name.NULL) {
					Join_List.add(con);
					//System.out.println("Join " + con.lhs.item_name.name() + " " + con.operator.name() + " " + con.rhs.item_name.name());
				} else if (con.lhs.table_name == tab_name_att_name.NULL
						&& con.rhs.table_name == tab_name_att_name.NULL) {
					throw new SQLParsingException("Meaningless condition");
				} else {
					BooleanExp_List.add(con);
					//System.out.println("Select " + con.lhs.item_name.name() + " " + con.lhs_s + " " + con.operator.name() + " " + con.rhs.item_name.name() + " " + con.rhs_s);
				}
			}
		}

	}

	private LinkedList<Field> Select_List = new LinkedList<Field>();

	private LinkedList<Field> Table_List = new LinkedList<Field>();

	private LinkedList<Condition> Join_List = new LinkedList<Condition>();

	private LinkedList<Condition> BooleanExp_List = new LinkedList<Condition>();
}
